#include "StdTcp.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "StdSqlite3.h"
#include "StdThread.h"
#include "StdThreadPool.h"
#include "DataCenter.h"
#include "../GlobalMessage.h"
#include "DoubleLinkList.h"
#include "FileSystem.h"

#define ip "192.168.192.128"
#define SERVER_PORT 8082

// //全局key
// char key[26] = "qazwsxedcrfvtgbyhnujmikolp";

DLlist Clientlist; // 定义一个全局的双向链表(在线用户列表)
FileSys *fs;       // 文件系统

char *GetFileNameFromPath(const char *filePath)
{
    char str[ContentSize] = {0};
    strcpy(str, filePath);

    char *dest = strtok(str, "/");
    char *fileName = NULL;
    while (dest != NULL)
    {
        fileName = dest;
        dest = strtok(NULL, "/");
    }
    char *result = strdup(fileName);
    return result;
}

// 发送文件到客户端
void SendFileToClient(MSG *m, int ClientSock)
{
    char *fileName = GetFileNameFromPath(m->Content);
    PackFile *pf = PacketFileInit(m->Content);

    memset(m->Content, 0, sizeof(m->Content));
    strcpy(m->Content + 4, fileName);
    int size = 1000;
    int count = 0;
    while (IsFileEnd(pf) == false)
    {
        ReadFromFile(pf, m->Content + 24, &size);
        // 填入读取的文件内容大小
        memcpy(m->Content, &size, sizeof(int));
        TcpServerSend(ClientSock, m, sizeof(MSG));
        count++;
        printf("msg flag : %d   这是第%d包数据,大小:%d\n", m->flag, count, size);
    }

    // 传输结束
    size = -1;
    memcpy(m->Content, &size, sizeof(int));
    TcpServerSend(ClientSock, m, sizeof(MSG));
    free(fileName);
    ClearPacketFile(pf);
}

char *GetOnlineList()
{
    char *content = (char *)malloc(ContentSize); // 在堆空间申请
    if (content == NULL)
    {
        printf("GetOnlineList malloc error\n");
        exit(-1);
    }
    memset(content, 0, ContentSize);
    DLNode *travelPoint = Clientlist.head->next;
    while (travelPoint != NULL)
    {
        CInfo *c = (CInfo *)travelPoint->data;
        strcat(content, c->ClientName);
        strcat(content, ","); // 解析标志
        travelPoint = travelPoint->next;
    }
    content[strlen(content) - 1] = '\0';
    return content;
}

/* 解决需求函数 */
void SolveRequest(MSG *m, int ClientSock)
{
    switch (m->flag)
    {
    case SIGNUP:
        /* 数据库当中没有（没注册）*/
        if (IsUserExist(m->FromName) == false)
        {
            if (AddNewUser(m->FromName, m->Content) == true)
            {
                InsertDLlistTial(&Clientlist, CreateCInfo(m->FromName, ClientSock));
                TravelDLlist(&Clientlist, PrintCInfo);
                memset(m->Content, ContentSize, 0);
                strcpy(m->Content, "注册成功");
                CreateNewDirInFs(fs, m->FromName);
            }
            else
            {
                memset(m->Content, ContentSize, 0);
                strcpy(m->Content, "服务器出错");
            }
        }
        else
        {
            memset(m->Content, ContentSize, 0);
            strcpy(m->Content, "用户名已被注册");
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    case LOGIN:
        // 账号是否存在
        if (IsUserExist(m->FromName) == true)
        {
            if (IsAccountEqual(m->FromName, m->Content) == true)
            {
                InsertDLlistTial(&Clientlist, CreateCInfo(m->FromName, ClientSock));
                TravelDLlist(&Clientlist, PrintCInfo);
                memset(m->Content, ContentSize, 0);
                strcpy(m->Content, "登录成功");
            }
            else
            {
                memset(m->Content, ContentSize, 0);
                strcpy(m->Content, "账号密码错误");
            }
        }
        else
        {
            memset(m->Content, ContentSize, 0);
            strcpy(m->Content, "账号不存在");
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    case SENDFILE:
        DLlist findList = FindByElement(&Clientlist, m->ToName, IsClientNameEqual);
        if (findList.len == 0)
        {
            printf("没有找到名称为|%s|的用户\n", m->ToName);
        }
        else
        {
            CInfo *c = (CInfo *)findList.head->next->data;
            printf("准备给|%s||套接字:%d|的用户发消息\n", c->ClientName, c->sock);
            int size = 0;
            memcpy(&size, m->Content, sizeof(int));

            if (size == -1)
            {
                char filename[NameSize] = {0};
                strcpy(filename, m->Content + 4);
                char str[ContentSize] = {0};
                sprintf(str, "文件|%s|传输完成!\n", filename);
                AddChatHistory(m->FromName, m->ToName, str);
            }

            TcpServerSend(c->sock, m, sizeof(MSG));
        }
        ClearDLlist(&findList, NULL);
        break;
    case CHAT:
        // 先判断用户是否存在
        if (IsUserExist(m->ToName) == false)
        {
            printf("没有找到名称为|%s|的用户\n", m->ToName);
            memset(m->Content, ContentSize, 0);
            strcpy(m->Content, "该用户不存在");
            TcpServerSend(ClientSock, m, sizeof(MSG));
        }
        // 在判断用户是否是好友
        else if (IsFriendExist(m->FromName, m->ToName) == false)
        {
            memset(m->Content, ContentSize, 0);
            strcpy(m->Content, "该用户不是你的好友");
            TcpServerSend(ClientSock, m, sizeof(MSG));
        }
        else
        {
            DLlist findList = FindByElement(&Clientlist, m->ToName, IsClientNameEqual);
            // 离线消息
            if (findList.len == 0) // 离线
            {
                AddChatHistory(m->FromName, m->ToName, m->Content);
                char *result = (char *)malloc(ContentSize);
                memset(result, 0, ContentSize);
                result = GetChatHiostory(m->FromName, m->ToName);
                printf("result:%s\n", result);
                memset(m->Content, 0, ContentSize);
                strcpy(m->Content, result);
                TcpServerSend(ClientSock, m, sizeof(MSG));
                free(result);
            }
            else
            {
                AddChatHistory(m->FromName, m->ToName, m->Content);
                CInfo *c = (CInfo *)findList.head->next->data;
                printf("准备给|%s||套接字：%d|的用户发送消息\n", c->ClientName, c->sock);
                char *result = (char *)malloc(ContentSize);
                memset(result, 0, ContentSize);
                result = GetChatHiostory(m->FromName, m->ToName);
                printf("result:%s\n", result);
                memset(m->Content, 0, ContentSize);
                strcpy(m->Content, result);
                free(result);
                TcpServerSend(c->sock, m, sizeof(MSG));
                TcpServerSend(ClientSock, m, sizeof(MSG));
                printf("content:%s", m->Content);
                ClearDLlist(&findList, NULL);
            }
        }

        break;
    // case BROADCAST:
    //     DLNode *travelPoint = Clientlist.head->next;
    //     while (travelPoint != NULL)
    //     {
    //         CInfo *c = (CInfo *)travelPoint->data;
    //         if (strcmp(c->ClientName, m->FromName) != 0)
    //         {
    //             TcpServerSend(c->sock, m, sizeof(MSG));
    //         }
    //         travelPoint = travelPoint->next;
    //     }
    //     break;
    case ONLINELIST:
    {
        char *content = GetOnlineList();
        printf("在线列表为：%s\n", content);
        strcpy(m->Content, content);
        TcpServerSend(ClientSock, m, sizeof(MSG));
        free(content);
        break;
    }

    case UPLOAD:
    {
        int size = 0;
        memcpy(&size, m->Content, 4);
        if (size == -1)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "UPDATEOK");
            TcpServerSend(ClientSock, m, sizeof(MSG));
            break;
        }

        char fileName[NameSize] = {0};
        strcpy(fileName, m->Content + 4);
        WriteFileToFs(fs, m->FromName, fileName, m->Content + 24, size);
        break;
    }
    case DOWNLOAD:
    {
        if (IsFileExist(fs, m->FromName, m->Content) == false)
        {
            strcpy(m->Content, "文件不存在！\n");
            TcpServerSend(ClientSock, m, sizeof(MSG));
        }
        else
        {
            char filePath[1600] = {0};
            char *filepath = GetServerFileDirPath(fs, m->FromName, m->Content);
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, filepath);
            SendFileToClient(m, ClientSock);
            free(filepath);
        }

        break;
    }
    case FILELIST:
    {
        char *list = GetFileList(fs, m->FromName);
        if (list == NULL)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "FILEERROR\n");
        }
        else
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, list);

            free(list);
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    }
    case ADDFRIEND:
        if (IsUserExist(m->ToName) == false)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "没有找到该用户\n");
        }
        else
        {
            AddNewFriend(m->FromName, m->ToName);

            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "好友请求已发出！\n");
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    case DELFRIEND:
        if (IsFriendExist(m->FromName, m->ToName) == false)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "该用户不是你的好友\n");
        }
        else
        {
            DelFriend(m->FromName, m->ToName);
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "已删除\n");
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    case SHOWFRIEND:
    {
        char *result = (char *)malloc(sizeof(ContentSize));
        memset(result, 0, sizeof(result));
        result = GetFriend(m->FromName);
        // int i = 1;
        // while (result[i] != NULL)
        // {
        //     memset(m->Content, 0, sizeof(m->Content));
        //     memcpy(m->Content, result[i], sizeof(result[i]));
        // }
        memset(m->Content, 0, sizeof(m->Content));
        strcpy(m->Content, result);
        free(result);
        printf("m.cont:%s\n", m->Content);
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    }
    case FRIENDREQUEST:
    {
        char *result = (char *)malloc(sizeof(ContentSize));
        memset(result, 0, sizeof(result));
        result = FriendRequest(m->FromName);
        memset(m->Content, 0, sizeof(m->Content));
        strcpy(m->Content, result);
        free(result);
        printf("m.cont:%s\n", m->Content);
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    }
    case ISFREIEND:
    {
        char ret[ContentSize] = {0};
        strcpy(ret, m->Content);
        ViewFlag(m->FromName, m->ToName, atoi(ret));
        AddNewFriend(m->FromName, m->ToName);
        ViewFlag(m->ToName, m->FromName, atoi(ret));
        if (atoi(ret) == 1)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "添加成功!\n");
        }
        else if (atoi(ret) == 2)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "已拒绝\n");
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    }

    case GREATEGROUP:
    {
        if (IsGroupExist(m->ToName) == true)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "群聊已经存在！");
        }
        else
        {
            AddGroup(m->FromName, m->ToName); // 创建群聊
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "群聊创建成功！");
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    }
    case DELETEGROUP:
    {
        if (IsGroupLeader(m->ToName, m->FromName) == false)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "您不是群主，不能删除群！");
        }
        else
        {
            if (DeleteGroup(m->ToName) == false)
            {
                printf("删除出错!\n");
                // return -1;
            }
            else
            {
                memset(m->Content, 0, sizeof(m->Content));
                strcpy(m->Content, "删除成功！");
            }
            TcpServerSend(ClientSock, m, sizeof(MSG));
        }
        break;
    }
    case JOINGROUP:
    {
        if (IsGroupExist(m->ToName) == false)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "群聊不存在！");
        }
        else
        {
            JoinGroup(m->ToName, m->FromName);
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "加入成功！");
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    }
    case LEAVEGROUP:
    {
        if (IsGroupExist(m->ToName) == false)
        {
            memset(m->Content, 0, sizeof(m->Content));
            strcpy(m->Content, "群聊不存在！");
        }
        else
        {
            if (IsGroupLeader(m->ToName, m->FromName) == true) // 如果为群主直接解散群
            {
                DisbandGroup(m->ToName);
                memset(m->Content, 0, sizeof(m->Content));
                strcpy(m->Content, "群聊已解散！");
            }
            else if (LeaveGroup(m->ToName, m->FromName) == false)
            {
                memset(m->Content, 0, sizeof(m->Content));
                strcpy(m->Content, "您不在该群聊！");
            }
            else
            {
                memset(m->Content, 0, sizeof(m->Content));
                strcpy(m->Content, "退出成功！");
            }
        }
        TcpServerSend(ClientSock, m, sizeof(MSG));
        break;
    }
    case CHATGROUP:
    {
        if (IsGroupExist(m->ToName) == false)
        {
            printf("没有找到名称为|%s|的群\n", m->ToName);
            memset(m->Content, ContentSize, 0);
            strcpy(m->Content, "该群不存在\n");
            TcpServerSend(ClientSock, m, sizeof(MSG));
        }
        else if (IsMember(m->ToName, m->FromName) == false)
        {
            memset(m->Content, ContentSize, 0);
            strcpy(m->Content, "您不在该群聊！\n");
            TcpServerSend(ClientSock, m, sizeof(MSG));
        }
        else
        {
            int size = 0; // 成员个数
            char **result = GetGroupMember(m->ToName, &size);
            DLNode *travelPoint = Clientlist.head->next;
            AddChatHistory(m->FromName, m->ToName, m->Content); // toname为群名字
            while (travelPoint != NULL)
            {
                CInfo *c = (CInfo *)travelPoint->data;
                for (int i = 1; i <= size; i++)
                {
                    if ((strcmp(c->ClientName, result[i]) == 0) && (strcmp(c->ClientName, m->FromName) != 0)) // 在线的群员且不是自己
                    {

                        printf("准备给|%s||套接字：%d|的用户发送消息\n", c->ClientName, c->sock);
                        char *result = (char *)malloc(ContentSize);
                        memset(result, 0, ContentSize);
                        result = GetGroupHistory(m->ToName);
                        printf("result:%s\n", result);
                        memset(m->Content, 0, ContentSize);
                        strcpy(m->Content, result);
                        free(result);
                        TcpServerSend(c->sock, m, sizeof(MSG));
                        printf("content:%s", m->Content);
                    }
                }
                travelPoint = travelPoint->next;
            }
            TcpServerSend(ClientSock, m, sizeof(MSG));
            FreeTableInfo(result);
        }
        break;
    }
    }
}

/* 线程处理函数(对客户端的处理逻辑) */
void *ClientHandle(void *arg)
{
    int clientSock = *((int *)arg); // 将指针arg转换为int类型的指针，然后再通过*解引用它获取对应内存地址上的整数值。
    /* 循环接收 */
    while (1)
    {
        MSG m;
        if (TcpServerRecv(clientSock, &m, sizeof(MSG)) == false)
        {
            printf("客户端|%d|下线\n", clientSock);
            break;
        }
        // printf("收到来自客户端|%d|的消息：%s\n", clientSock, msg);

        SolveRequest(&m, clientSock);
    }
    /* 删除用户信息 */
    RemoveByElement(&Clientlist, (void *)&clientSock, IsClientSockEqual, free); // 最后一个参数用于释放链表当中的结构体指针
    return NULL;
}

int main()
{

    if (DataCenterInit() == false)
    {
        printf("数据中心初始化失败！\n");
        return -1;
    }

    InitDLlist(&Clientlist);

    TcpS *s = TcpServerInit(ip, SERVER_PORT);

    ThreadP *p = ThreadPoolInit(10, 2, 10, 3600);
    fs = FileSystemInit("./filesystem");

    /* 循环accept */
    int clientSock = -1;
    while ((clientSock = TcpServerAccept(s)) >= 0)
    {
        printf("接入新的客户端，套接字为：%d\n", clientSock);
        ThreadPoolAddTask(p, ClientHandle, &clientSock); // 加入线程池
    }

    return 0;
}